package adfc.game;

import java.nio.ByteBuffer;
import java.nio.ShortBuffer;

import static adfc.game.GameConstants.*;

/**
 * Created by IntelliJ IDEA.
 * User: aimozg
 * Date: 31.12.11
 * Time: 17:43
 */
public class Chunk {
    public final ShortBuffer raw_blocks;
    public final int[] cacheHeightmap;

    public short block(int x, int y, int z) {
        return raw_blocks.get(offset(x, y, z));
    }

    public void block(int x, int y, int z, short block) {
        raw_blocks.put(offset(x, y, z), block);
        blockUpdated(x, y, z);
    }

    public static int xyoffset(int x, int y) {
        return y * CHUNK_XY_SIZE + x;
    }

    public static int offset(int x, int y, int z) {
        return z * CHUNK_XY_SIZE * CHUNK_XY_SIZE + y * CHUNK_XY_SIZE + x;
    }

    public Chunk() {
        raw_blocks = ByteBuffer.allocateDirect(CHUNK_XY_SIZE * CHUNK_XY_SIZE * CHUNK_Z_SIZE * T_BLOCKTYPE_BYTES).asShortBuffer();
        cacheHeightmap = new int[CHUNK_XY_SIZE * CHUNK_XY_SIZE];
    }

    public void blockUpdated(int x, int y, int z) {
        int xyoffset = xyoffset(x, y);
        int oldHeightmap = cacheHeightmap[xyoffset];
        Block newBlock = Block.forId(block(x, y, z));
        if (z > oldHeightmap && newBlock.solid) cacheHeightmap[xyoffset] = z;
        else if (z == oldHeightmap && !newBlock.solid) {
            cacheHeightmap[xyoffset] = 0;
            for (; z >= 0; z--) {
                if (Block.forId(block(x, y, z)).solid) cacheHeightmap[xyoffset] = z;
            }
        }
    }

    public void blocksUpdated() {
        blocksUpdated(0, CHUNK_XY_SIZE - 1, 0, CHUNK_XY_SIZE - 1, 0, CHUNK_Z_SIZE - 1);
    }

    public void blocksUpdated(int x0, int x1, int y0, int y1, int z0, int z1) {
        calculateHeightmap(x0, x1, y0, y1);
    }

    private void calculateHeightmap(int x0, int x1, int y0, int y1) {
        for (int y = y0; y <= y1; y++) {
            for (int x = x0; x <= x1; x++) {
                int hm = 0;
                for (int z = CHUNK_Z_SIZE - 1; z > 0; z--) {
                    if (Block.forId(block(x, y, z)).solid) {
                        hm = z;
                        break;
                    }
                }
                cacheHeightmap[xyoffset(x, y)] = hm;
            }
        }
    }
}
